﻿/**
 ** @作者:	   王桂龙 QQ731513122
 ** @日期:	   2019.12.6
 ** @简介:     指北针
 **           
 */
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Drawing2D;

namespace BHXJDOTNET.NEW
{
    /// <summary>
    /// 指北针
    /// </summary>
    public partial class BHXJComPass : UserControl, IBHXJZOOM
    {
        #region 继承于ZOOM接口的属性和方法
        private Point _OriginPoint = new Point(0, 0);
        /// <summary>
        /// 原点
        /// </summary>
        public Point OriginPoint
        {
            get
            { return this._OriginPoint; }
            set
            {
                if (this._OriginPoint != value)
                {
                    this._OriginPoint = value;
                    if (DesignMode)
                        this.IniLocation = this.BHXJGetIniLocationInDesignMode();
                }
            }
        }
        private bool _AutoOrigin = false;
        /// <summary>
        /// 自动更改原点模式(只在设计模式下有用)
        /// </summary>
        public bool AutoOrigin
        {
            get
            {
                return this._AutoOrigin;
            }
            set
            {
                if (this._AutoOrigin != value)
                {
                    this._AutoOrigin = value;
                    if (DesignMode)
                    {
                        if (this.AutoOrigin)
                        {
                            this.OriginPoint = this.Location;
                        }
                        else
                        {
                            this.OriginPoint = new Point(0, 0);
                        }
                    }
                }
            }
        }
        /// <summary>
        /// 初始尺寸
        /// </summary>
        [Browsable(false)]
        public Size IniSize { get; set; }
        /// <summary>
        /// 初始位置
        /// </summary>
        [Browsable(false)]
        public Point IniLocation { get; set; }
        /// <summary>
        /// 初始字体
        /// </summary>
        [Browsable(false)]
        public Font IniFont { get; set; }


        private double _SizeScale = 1;
        /// <summary>
        /// 尺寸比例
        /// </summary>
        [Browsable(false)]
        public double SizeScale
        {
            get { return this._SizeScale; }
            set
            {
                if (this._SizeScale != value)
                {
                    this._SizeScale = value;
                }
            }
        }


        private double _LocationScale = 1;
        /// <summary>
        /// 位置比例
        /// </summary>
        [Browsable(false)]
        public double LocationScale
        {
            get { return this._LocationScale; }
            set
            {
                if (this._LocationScale != value)
                {
                    this._LocationScale = value;
                }
            }
        }
        private double _FontScale = 1;
        /// <summary>
        /// 字体比例
        /// </summary>
        [Browsable(false)]
        public double FontScale
        {
            get { return this._FontScale; }
            set
            {
                if (this._FontScale != value)
                {
                    this._FontScale = value;
                }
            }
        }
        #endregion


        public new Color BackColor
        {
            get {return base.BackColor; }
            set
            {
                if (base.BackColor != value)
                {
                    base.BackColor = value;
                    this.resetbictmap = true;
                }
            }
        }



        private Color _PointerColor = Color.Aqua;
        /// <summary>
        /// 指针颜色
        /// </summary>
        [Description("指针颜色"), Category("BHXJ")]
        public Color PointerColor
        {
            get { return this._PointerColor; }
            set
            {
                if (this._PointerColor != value)
                {
                    this._PointerColor = value;
                    this.Invalidate();
                    
                }
            }
        }

        private bool _PointerMove = false;
        [Description("指针移动"), Category("BHXJ")]
        public bool PointerMove
        {
            get { return this._PointerMove; }
            set
            {
                if (this._PointerMove != value)
                {
                    this._PointerMove = value;
                    this.Invalidate();
                }
            }
        }

        private Color _NormalColor = Color.FromArgb(255, 100, 100, 100);
        /// <summary>
        /// 常规标志文字颜色
        /// </summary>
        [Description("常规标志文字颜色"), Category("BHXJ")]
        public Color NormalColor
        {
            get { return this._NormalColor; }
            set
            {
                if (this._NormalColor != value)
                {
                    this._NormalColor = value;
                    this.resetbictmap = true;
                    this.Invalidate();
                }
            }
        }

        #region 东南西北方向颜色
        private Color _N_Color = Color.Aqua;
        /// <summary>
        /// 北颜色
        /// </summary>
        [Description("北颜色"), Category("BHXJ")]
        public Color Color_N
        {
            get { return this._N_Color; }
            set
            {
                if (this._N_Color != value)
                {
                    this._N_Color = value;
                    this.resetbictmap = true;
                    this.Invalidate();
                }
            }
        }

        private Color _S_Color = Color.Red;
        /// <summary>
        /// 南颜色
        /// </summary>
        [Description("南颜色"), Category("BHXJ")]
        public Color Color_S
        {
            get { return this._S_Color; }
            set
            {
                if (this._S_Color != value)
                {
                    this._S_Color = value;
                    this.resetbictmap = true;
                    this.Invalidate();
                }
            }
        }

        private Color _W_Color = Color.FromArgb(255, 100, 100, 100);
        /// <summary>
        /// 西颜色
        /// </summary>
        [Description("西颜色"), Category("BHXJ")]
        public Color Color_W
        {
            get { return this._W_Color; }
            set
            {
                if (this._W_Color != value)
                {
                    this._W_Color = value;
                    this.resetbictmap = true;
                    this.Invalidate();
                }
            }
        }

        private Color _E_Color = Color.FromArgb(255, 100, 100, 100);
        /// <summary>
        /// 东颜色
        /// </summary>
        [Description("东颜色"), Category("BHXJ")]
        public Color Color_E
        {
            get { return this._E_Color; }
            set
            {
                if (this._E_Color != value)
                {
                    this._E_Color = value;
                    this.resetbictmap = true;
                    this.Invalidate();
                }
            }
        }
        #endregion

        private float _Direction = 0;
        /// <summary>
        /// 方向
        /// </summary>
        [Description("方向值"), Category("BHXJ")]
        public float Direction
        {
            get { return _Direction; }
            set
            {
                if (this._Direction != value)
                {
                    this._Direction = value;

                    if (this._Direction < 0)
                    {
                        this._Direction = 360 - Math.Abs(this._Direction) % 360;
                    }
                    else
                    {
                        this._Direction = Math.Abs(this._Direction) % 360;
                    }

                    this.Invalidate();
                    //this.LocalDirection = (int)Math.Round(value, 0);
                }
            }
        }

        private bool _ShowScaleValue = true;
        /// <summary>
        /// 显示刻度值
        /// </summary>
        [Description("显示刻度值"), Category("BHXJ")]
        public bool ShowScaleValue
        {
            get { return this._ShowScaleValue; }
            set
            {
                if (this._ShowScaleValue != value)
                {
                    this._ShowScaleValue = value;
                    this.resetbictmap = true;
                    this.Invalidate();
                }
            }
        }

        private bool _Han = true;
        /// <summary>
        /// 汉字
        /// </summary>
        [Description("汉字"), Category("BHXJ")]
        public bool Han
        {
            get { return this._Han; }
            set
            {
                if (this._Han != value)
                {
                    this._Han = value;
                    this.resetbictmap = true;
                    this.Invalidate();
                }
            }
        }

        /// <summary>
        /// _有边框
        /// </summary>
        private bool _HasFrame = true;
        [Description("有边框"), Category("BHXJ")]
        /// <summary>
        /// 有边框
        /// </summary>
        public bool HasFrame
        {
            get { return this._HasFrame; }
            set
            {
                if (this._HasFrame != value)
                {
                    this._HasFrame = value;
                    this.Invalidate(false);
                }
            }
        }

        /// <summary>
        /// _边框颜色
        /// </summary>
        private Color _FrameColor = Color.FromArgb(64, 64, 64);
        [Description("边框颜色,设置为父控件背景色可以遮挡锯齿"), Category("BHXJ")]
        /// <summary>
        /// 边框颜色
        /// </summary>
        public Color FrameColor
        {
            get
            {
                return this._FrameColor;
            }
            set
            {
                if (this._FrameColor != value)
                {
                    this._FrameColor = value;
                    this.Invalidate(false);
                }
            }
        }

        public new Font Font{get;set;}


        public BHXJComPass()
        {
            InitializeComponent();
            this.SetStyle(ControlStyles.UserPaint, true);
            this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
            this.SetStyle(ControlStyles.DoubleBuffer, true);
            this.SetStyle(ControlStyles.ResizeRedraw, false);
            this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);


            this.Margin = new Padding(0);
            this.ForeColor = Color.Gray;

            #region 设计时,变化事件
            if (System.ComponentModel.LicenseManager.UsageMode == System.ComponentModel.LicenseUsageMode.Designtime)
            {
                //设计时事件
                this.SizeChanged += new EventHandler(this.BHXJ_SizeChangedInDesignMode);
                this.FontChanged += new EventHandler(this.BHXJ_FontChangedInDesignMode);
                this.LocationChanged += new EventHandler(this.BHXJ_LocationChangedInDesignMode);
            }
            #endregion

            //防止字体在设计器中添加该控件时候自动追随父控件
            this.Font = this.Font;
            //缩放模式设置为无
            this.AutoScaleMode = AutoScaleMode.None;

            //设置初始
            this.IniSize = this.Size;
            this.IniFont = this.Font;
            this.IniLocation = this.BHXJGetIniLocationInDesignMode();

            this.FontChanged += BHXJComPass_FontChanged;
            this.SizeChanged += BHXJComPass_SizeChanged;

            for(int i=0;i<3;++i)
            {
                curvePoints[i] = new PointF(0,0);
            }
        }

        private void BHXJComPass_SizeChanged(object sender, EventArgs e)
        {
            this.resetbictmap = true;
            this.Invalidate();
        }

        private void BHXJComPass_FontChanged(object sender, EventArgs e)
        {
            this.resetbictmap = true;
            this.Invalidate();
        }
        bool resetbictmap = false;
        private Bitmap bitmap = null;
        RectangleF rf = new RectangleF();
        StringFormat textFormat = new StringFormat();

        SolidBrush brush = new SolidBrush(Color.White);
        Pen markpen = new Pen(Color.White, 1);
        PointF[] curvePoints = new PointF[3];
        private void setbitmap(float b)
        {
            //判断是否需要重置，不需要则直接返回
            if (bitmap != null && bitmap.Width == b&&(!this.resetbictmap))
                return;
            bitmap = new Bitmap((int)b,(int)b);
            Graphics g = Graphics.FromImage(bitmap);
            //g.FillRectangle(new SolidBrush(this.BackColor), 0, 0, b, b);
            g.SmoothingMode = SmoothingMode.AntiAlias;

            g.FillPie(new SolidBrush(this.BackColor), 0, 0, b, b,0, 360);
            SolidBrush solidBrush = new SolidBrush(this.FrameColor);
            
            g.DrawArc(new Pen(solidBrush,2), -1, -1, b+2, b+2, 0, 360);
            g.TranslateTransform(b / 2, b / 2);

            //字体
            Font textfont = new Font(this.Font.FontFamily, b / 16f, this.Font.Style);
            //#region 普通标志
            //markpen.Color = this._NormalColor;
            //markpen.Width = b / 24;
            //this.SetRectangleF(b * 19f / 24f, ref rf);
            //for (int i = 0; i < 360; i += 5)
            //{
            //    if (i != 90 && i != 180 && i != 270 && i != 0)
            //        this.DrawMark(g, rf, markpen, i);
            //}
            //#endregion

            //#region 正方向标志
            //this.SetRectangleF(b * 0.75f + 1f, ref rf);
            //float nswewith = b / 12;
            //markpen.Color = this._N_Color;
            //markpen.Width = nswewith;
            //this.DrawMark(g, rf, markpen, -90);

            //markpen.Color = this._S_Color;
            //markpen.Width = nswewith;
            //this.DrawMark(g, rf, markpen, 90);

            //markpen.Color = this._W_Color;
            //markpen.Width = nswewith;
            //this.DrawMark(g, rf, markpen, 180);

            //markpen.Color = this._E_Color;
            //markpen.Width = nswewith;
            //this.DrawMark(g, rf, markpen, 0);
            //#endregion
            #region 标志文字
           // g.SmoothingMode = SmoothingMode.None;
            textFormat.Alignment = StringAlignment.Center;
            textFormat.LineAlignment = StringAlignment.Near;
            this.SetRectangleF(b, ref rf);

            brush.Color = this._N_Color;
            #region 东南西北四方向文字
            if (this._Han)
            {
                this.DrawString(g, "北", rf, brush, textfont, textFormat);
                g.RotateTransform(90);
                brush.Color = this._E_Color;
                this.DrawString(g, "东", rf, brush, textfont, textFormat);
                g.RotateTransform(90);
                brush.Color = this._S_Color;
                this.DrawString(g, "南", rf, brush, textfont, textFormat);
                g.RotateTransform(90);
                brush.Color = this._W_Color;
                this.DrawString(g, "西", rf, brush, textfont, textFormat);
                g.RotateTransform(90);
            }
            else
            {
                this.DrawString(g, "N", rf, brush, textfont, textFormat);
                g.RotateTransform(90);
                brush.Color = this._E_Color;
                this.DrawString(g, "E", rf, brush, textfont, textFormat);
                g.RotateTransform(90);
                brush.Color = this._S_Color;
                this.DrawString(g, "S", rf, brush, textfont, textFormat);
                g.RotateTransform(90);
                brush.Color = this._W_Color;
                this.DrawString(g, "W", rf, brush, textfont, textFormat);
                g.RotateTransform(90);
            }
            #endregion

            if (this._ShowScaleValue)
            {
                this.SetRectangleF(b * 23f / 24f, ref rf);
                textfont = new Font(this.Font.FontFamily, b / 36f, this.Font.Style);
                int step = 15;
                brush.Color = this._NormalColor;
                for (int i = 0; i < 360; i += step)
                {
                    g.RotateTransform(step);
                    int a = i + step;
                    if (a != 90 && a != 180 && a != 270 && a != 360)
                        this.DrawString(g, a.ToString(), rf, brush, textfont, textFormat);
                }
            }
            #endregion        

            this.resetbictmap = false;
        }
        protected override void OnPaint(PaintEventArgs e)
        {
            //base.OnPaint(e);

            try
            {
                Graphics g = e.Graphics;
                g.SmoothingMode = SmoothingMode.AntiAlias;

                //边长
                float b = this.Width > this.Height ? this.Height : this.Width;
                //区域
                GraphicsPath gp = new GraphicsPath();
                gp.AddArc(new RectangleF((this.Width - b) / 2, (this.Height - b) / 2, b, b), 0, 360);
                this.Region = new Region(gp);


                //中心
                g.TranslateTransform(((float)this.Width) / 2-0.5f, ((float)this.Height) / 2-0.5f);

                Font textfont;



                float angle = 360 - _Direction;
                if (!this.PointerMove)
                {
                    g.RotateTransform(angle);
                }
                //重置背景图
                this.setbitmap(b);
                this.SetRectangleF(b, ref rf);
                g.DrawImage(this.bitmap, rf);
                #region 普通标志
                markpen.Color = this._NormalColor;
                markpen.Width = b / 24;
                this.SetRectangleF(b * 19f / 24f, ref rf);
                for (int i = 0; i < 360; i += 5)
                {
                    if (i != 90 && i != 180 && i != 270 && i != 0)
                        this.DrawMark(g, rf, markpen, i);
                }
                #endregion

                #region 正方向标志
                this.SetRectangleF(b * 0.75f + 1f, ref rf);
                float nswewith = b / 12;
                markpen.Color = this._N_Color;
                markpen.Width = nswewith;
                this.DrawMark(g, rf, markpen, -90);

                markpen.Color = this._S_Color;
                markpen.Width = nswewith;
                this.DrawMark(g, rf, markpen, 90);

                markpen.Color = this._W_Color;
                markpen.Width = nswewith;
                this.DrawMark(g, rf, markpen, 180);

                markpen.Color = this._E_Color;
                markpen.Width = nswewith;
                this.DrawMark(g, rf, markpen, 0);
                #endregion


                g.RotateTransform(_Direction);

                #region 指针
                curvePoints[0].X = 0.0f; //- 0.25f;
                curvePoints[0].Y = -b * 0.375f;
                curvePoints[1].X = -b / 30;
                curvePoints[1].Y = -b * 0.325f;
                curvePoints[2].X = b / 30;
                curvePoints[2].Y = -b * 0.325f;
                brush.Color = this.PointerColor;
                g.FillPolygon(brush, curvePoints);
                #endregion

                if (this.PointerMove)
                {
                    g.RotateTransform(angle);
                }
                #region 方向和角度文字
                //字体
                textfont = new Font(this.Font.FontFamily, b / 12f, this.Font.Style);

                brush.Color = this.ForeColor;

                //边框
                this.SetRectangleF(b, ref rf);
                if (this._HasFrame)
                    g.DrawArc(new Pen(this.FrameColor, 2), rf, 0, 360);

                //方向文字
                rf.Location = new PointF(-(b / 2), -(b / 2));
                rf.Size = new SizeF(b, b / 2);
                textFormat.Alignment = StringAlignment.Center;
                textFormat.LineAlignment = StringAlignment.Far;
                string dir = this.GetDirectionString(this.Direction);
                g.DrawString(dir, textfont, brush, rf, textFormat);

                //角度
                rf.Location = new PointF(-(b / 2), 0);
                rf.Size = new SizeF(b, b / 2);
                textFormat.Alignment = StringAlignment.Center;
                textFormat.LineAlignment = StringAlignment.Near;
                g.DrawString(this.Direction.ToString("f1") + "度", textfont, brush, rf, textFormat);
                #endregion

               

            }
            catch
            {

            }
        }

        private string GetDirectionString(float angle)
        {
            string ret = "";
            if ((angle >= 337.5 && angle < 360) || (angle >= 0 && angle < 22.5))
            {
                ret += "北";
            }
            if (angle >= 22.5 && angle < 67.5)
            {
                ret += "东北";
            }
            if (angle >= 67.5 && angle < 112.5)
            {
                ret += "东";
            }
            if (angle >= 112.5 && angle < 157.5)
            {
                ret += "东南";
            }
            if (angle >= 157.5 && angle < 202.5)
            {
                ret += "南";
            }
            if (angle >= 202.5 && angle < 247.5)
            {
                ret += "西南";
            }
            if (angle >= 247.5 && angle < 292.5)
            {
                ret += "西";
            }
            if (angle >= 292.5 && angle < 337.5)
            {
                ret += "西北";
            }
            return ret;
        }

        private void DrawString(Graphics g,string s, RectangleF rfText, Brush fontBrush, Font font, StringFormat stringFormat)
        {
            try
            {
                g.DrawString(s, font, fontBrush, rfText, stringFormat);
            }
            catch
            { }
        }

        private void DrawString(Graphics g, string s, float y, Brush fontBrush, Font font)
        {
            try
            {
                StringFormat stringFormat = new StringFormat();
                stringFormat.LineAlignment = StringAlignment.Center;
                stringFormat.Alignment= StringAlignment.Center;
                SizeF sf = g.MeasureString(s, font);
                RectangleF rfText = new RectangleF();
                rfText.Location = new PointF(-sf.Width / 2, y - sf.Height / 2);
                rfText.Size = sf;
                g.DrawString(s, font, fontBrush, rfText, stringFormat);
            }
            catch
            { }
        }

        private void SetRectangleF(float rfb, ref RectangleF rf)
        {
            float xy = -(rfb * 0.5f);
            rf.Location = new PointF(xy, xy);
            rf.Size = new SizeF(rfb, rfb);
        }

        private void DrawMark(Graphics g, RectangleF rf, Pen p, float angle)
        {
            try
            {
                g.DrawArc(p, rf, angle-0.5f , 1);
            }
            catch
            {

            }
        }
    }
}
